package com.atguigu.service;

import com.atguigu.dao.OrderDao;
import com.atguigu.dao.StockDao;
import com.atguigu.dao.UserDao;
import com.atguigu.entity.Order;
import com.atguigu.entity.Stock;
import com.atguigu.entity.User;
import com.atguigu.util.SaltUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;

import java.util.Date;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

@Service
@Transactional
@Slf4j
public class OrderServiceImpl implements OrderService {

    @Autowired
    private OrderDao orderDao;

    @Autowired
    private StockDao stockDao;

    @Autowired
    private UserDao userDao;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;





    // 单用户限制次数
    @Override
    public String createOrderAfterMd5Limit(String userId, String stockId, String Md5) {
        // 实际中判断过期在前面，这里不加过期判断
        // 先看看该商品是否已经过期了（抢购时间已过）
//        if (!stringRedisTemplate.hasKey("kill"+stockId)) {
//            //已经过期
//            throw new RuntimeException("秒杀活动已经结束啦~~");
//        }
        // 获取redis的大 key
        String hashKey = "KEY_" + userId + "_" + stockId;
        String s = stringRedisTemplate.opsForValue().get(hashKey);

        if (s == null) throw new RuntimeException("未携带验证签名，请求不合法！");
//        System.out.println(s);
//        System.out.println(Md5);
//        System.out.println(s.equals(Md5));
        if (!s.equals(Md5)) {
            throw new RuntimeException("验证信息不通过，请求不合法，请重新抢购！");
        }

        try {

            // 校验库存
            Stock stock = checkStock(stockId);
            //扣库存
            updateSale(stock);
            //下订单
            return createOrder(stock);
        }catch (Exception e){
            e.printStackTrace();
            return e.getMessage();
        }
    }


    @Override
    public String getMd5(String userId, String stockId) {
        // 先检查用户信息合法性
        User user = userDao.findById(userId);
        if (Objects.isNull(user)) {
            throw new RuntimeException("用户信息不合法：用户不存在！");
        }
        // 检查请求商品的合法性
        Stock stock = stockDao.findById(stockId);
        if (Objects.isNull(stock)) {
            throw new RuntimeException("商品信息不合法：商品不存在！");
        }
        // 生成 Md5签名
        String hashKey = "KEY_" + userId + "_" + stockId;
        // 加入随机盐  随机算法生成
        String salt = SaltUtils.getSalt(8);
        String md5Code = DigestUtils.md5DigestAsHex((hashKey + salt).getBytes());
        // 设置时限
        stringRedisTemplate.opsForValue().set(hashKey, md5Code, 120, TimeUnit.SECONDS);

        return md5Code;
    }

    @Override
    public String createOrderAfterMd5(String userId, String stockId, String Md5) {
        // 实际中判断过期在前面，这里不加过期判断
        // 先看看该商品是否已经过期了（抢购时间已过）
//        if (!stringRedisTemplate.hasKey("kill"+stockId)) {
//            //已经过期
//            throw new RuntimeException("秒杀活动已经结束啦~~");
//        }
        // 获取redis的大 key
        String hashKey = "KEY_" + userId + "_" + stockId;
        String s = stringRedisTemplate.opsForValue().get(hashKey);

        if (s == null) throw new RuntimeException("未携带验证签名，请求不合法！");
        System.out.println(s.equals(Md5));
        if (!s.equals(Md5)) {
            throw new RuntimeException("验证信息不通过，请求不合法，清重新抢购！");
        }

        // 校验库存
        Stock stock = checkStock(stockId);
        //扣库存
        updateSale(stock);
        //下订单
        return createOrder(stock);
    }



    public String createOrder(String sid) {
        // 先看看该商品是否已经过期了（抢购时间已过）
        if (!stringRedisTemplate.hasKey("kill" + sid)) {
            //已经过期
            throw new RuntimeException("秒杀活动已经结束啦~~");
        }

        // 校验库存
        Stock stock = checkStock(sid);
        //扣库存
        updateSale(stock);
        //下订单
        return createOrder(stock);
    }

    // 校验库存
    private Stock checkStock(String id) {
        Stock stock = stockDao.findById(id);
        if (stock.getSale() == stock.getCount()) {
            throw new RuntimeException("库存不足！");
        }
        return stock;
    }

    // 扣除库存
    private void updateSale(Stock stock) {
        /*使用乐观锁，更新操作在数据库层面更新*/
        //stock.setSale(stock.getSale()+1);
        // 根据商品id扣除库存
        int updateRow = stockDao.updateSale(stock);
        if (updateRow == 0) {
            throw new RuntimeException("抢购失败，请重试！");
        }

    }

    // 创建订单
    private String createOrder(Stock stock) {
        Order order = new Order();
        order.setStockId(stock.getId()).setCreateTime(new Date()).setName(stock.getName());

        orderDao.save(order);
        //因为mapper.xml文件中指定了id是自增的，所以插入后会返回id
//        System.out.println("createOrder...");
//        System.out.println(order);
        return order.getId();
    }
}
